package jch.learn.java.advanced.chapter1_stream.parallel;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.*;

// 并行流
public class ParallelStreams {

    // 使用并行流需要满足的条件：
    // 1、数据应该在内存中。必须等到数据到达是非常低效的。
    // 2、流应该可以被高效地分成若干个子部分。由数组或平衡二叉树支撑的流都可以工作得很好，但是Stream.iterate返回得结果不行。
    // 3、流操作的工作量应该具有较大的规模。若总工作负载并不是很大，那么搭建并行计算时所付出的代价就没什么意义。
    // 4、流操作不应该被阻塞。
    // 即：不是所有流都可以转换为并行流，只有在对已经位于内存中的数据执行大量计算操作时，才应该使用并行流。

    public static void main(String[] args) throws URISyntaxException, IOException {
        String contents = new String(Files.readAllBytes(Paths.get(ParallelStreams.class.getResource("/gutenberg/alice30.txt").toURI())), StandardCharsets.UTF_8);
        List<String> wordList = Arrays.asList(contents.split("\\PL+"));

        // java.util.stream.BaseStream<T,S extends BaseStream<T,S>>

        // S parallel()  产生一个与当前流中元素相同的并行流
        // S unordered()  产生一个与当前流中元素相同的无序流

        // java.util.Collection<E>

        // Stream<E> parallelStream() 用当前集合中的元素产生一个并行流

        int[] shortWords = new int[10];
        wordList.parallelStream().forEach(s -> {
            if (s.length() < 10) shortWords[s.length()]++;
        });
        System.out.println(Arrays.toString(shortWords));

        Arrays.fill(shortWords, 0);
        wordList.parallelStream().forEach(s -> {
            if (s.length() < 10) shortWords[s.length()]++;
        });
        System.out.println(Arrays.toString(shortWords));

        Map<Integer,Long> shortWordCounts = wordList.parallelStream().filter(s -> s.length() < 10).collect(groupingBy(String::length,counting()));
        System.out.println(shortWordCounts);

        Map<Integer,List<String>> result = wordList.parallelStream().collect(Collectors.groupingByConcurrent(String::length));
        System.out.println(result.get(14));

        result = wordList.parallelStream().collect(Collectors.groupingByConcurrent(String::length));
        System.out.println(result.get(14));

        Map<Integer,Long> wordCounts = wordList.parallelStream().collect(groupingByConcurrent(String::length,counting()));
        System.out.println(wordCounts);
    }

}
